﻿// This code is released under the BSD license.
namespace PugLib.Conditions
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Net;

    /// <summary>
    /// Static functions to map search operations to objects and type comparisons
    /// 
    /// Can't use generics here because the type isn't known until run time and not all logical operators are defined for all types
    /// 
    /// This ugly class is a small price to pay, even initially, for the flexibility of the search system it provides.
    /// </summary>
    internal static class SearchMethods
    {
        #region GreaterThan

        public static bool GreaterThan(string instance, string search)
        {
            // string < string isn't defined, so do an endswith...
            return EndsWith(instance, search);
        }

        public static bool GreaterThan(DateTime instance, string search)
        {
            DateTime dt;
            if (DateTime.TryParse(search, out dt))
            {
                return instance > dt;
            }
            if (search.Length == 4)
            {
                // assume year...
                dt = new DateTime(SafeConvert.ToInt32(search), 1, 1);
                return instance > dt;
            }
            return GreaterThan(instance.ToString(), search);
        }

        public static bool GreaterThan(DateTime? instance, string search)
        {
            if (instance.HasValue)
            {
                return GreaterThan((DateTime)instance, search);
            }
            return true;
        }

        public static bool GreaterThan(IPAddress instance, string search)
        {
            // obj > obj isn't defined, so do a startswith...
            return GreaterThan(instance, search);
        }

        public static bool GreaterThan(CultureInfo instance, string search)
        {
            // obj > obj isn't defined, so do a startswith...
            return GreaterThan(instance, search);
        }

        public static bool GreaterThan(int instance, string search)
        {
            return instance > SafeConvert.ToInt32(search);
        }

        public static bool GreaterThan(short instance, string search)
        {
            return instance > SafeConvert.ToInt16(search);
        }

        public static bool GreaterThan(short? instance, string search)
        {
            return instance > SafeConvert.ToInt16(search);
        }

        #endregion GreaterThan

        #region LessThan

        public static bool LessThan(string instance, string search)
        {
            // string < string isn't defined, so do a startswith...
            return StartsWith(instance, search);
        }

        public static bool LessThan(DateTime instance, string search)
        {
            DateTime dt;
            if (DateTime.TryParse(search, out dt))
            {
                return instance < dt;
            }
            if (search.Length == 4)
            {
                // assume year...
                dt = new DateTime(SafeConvert.ToInt32(search), 1, 1);
                return instance < dt;
            }
            return LessThan(instance.ToString(), search);
        }

        public static bool LessThan(DateTime? instance, string search)
        {
            if (instance.HasValue)
            {
                return LessThan((DateTime)instance, search);
            }
            return true;
        }

        public static bool LessThan(IPAddress instance, string search)
        {
            // obj < obj isn't defined, so do a startswith...
            return StartsWith(instance, search);
        }

        public static bool LessThan(CultureInfo instance, string search)
        {
            // obj < obj isn't defined, so do a startswith...
            return StartsWith(instance, search);
        }

        public static bool LessThan(int instance, string search)
        {
            return instance < SafeConvert.ToInt32(search);
        }

        public static bool LessThan(short instance, string search)
        {
            return instance < SafeConvert.ToInt16(search);
        }

        public static bool LessThan(short? instance, string search)
        {
            return instance < SafeConvert.ToInt16(search);
        }

        #endregion LessThan

        #region Is

        public static bool Is(string instance, string search)
        {
            return string.Equals(instance, search, StringComparison.OrdinalIgnoreCase);
        }

        public static bool Is(DateTime instance, string search)
        {
            DateTime dt;
            if (DateTime.TryParse(search, out dt))
            {
                return instance.Date == dt.Date;
            }
            return false;
        }

        public static bool Is(DateTime? instance, string search)
        {
            if (instance.HasValue)
            {
                return Is((DateTime)instance, search);
            }
            return false;
        }

        public static bool Is(IPAddress instance, string search)
        {
            return Is(SafeConvert.ToString(instance), search);
        }

        public static bool Is(CultureInfo instance, string search)
        {
            return Is(SafeConvert.ToString(instance), search);
        }

        public static bool Is(int instance, string search)
        {
            return instance == SafeConvert.ToInt32(search);
        }

        public static bool Is(short instance, string search)
        {
            return instance == SafeConvert.ToInt16(search);
        }

        public static bool Is(short? instance, string search)
        {
            return instance == SafeConvert.ToInt16(search);
        }

        #endregion

        #region IsNot

        public static bool IsNot(string instance, string search)
        {
            return !Is(instance, search);
        }

        public static bool IsNot(DateTime instance, string search)
        {
            return !Is(instance, search);
        }

        public static bool IsNot(DateTime? instance, string search)
        {
            if (instance.HasValue)
            {
                return IsNot((DateTime)instance, search);
            }
            return true;
        }

        public static bool IsNot(IPAddress instance, string search)
        {
            return IsNot(SafeConvert.ToString(instance), search);
        }

        public static bool IsNot(CultureInfo instance, string search)
        {
            return IsNot(SafeConvert.ToString(instance), search);
        }

        public static bool IsNot(int instance, string search)
        {
            return instance != SafeConvert.ToInt32(search);
        }

        public static bool IsNot(short instance, string search)
        {
            return instance != SafeConvert.ToInt16(search);
        }

        public static bool IsNot(short? instance, string search)
        {
            return instance != SafeConvert.ToInt16(search);
        }

        #endregion IsNot

        #region Contains

        public static bool Contains(string instance, string search)
        {
            instance = instance ?? string.Empty;
            return (-1 < instance.IndexOf(search, StringComparison.OrdinalIgnoreCase));
        }

        public static bool Contains(DateTime instance, string search)
        {
            return Contains(instance.ToString(), search);
        }

        public static bool Contains(DateTime? instance, string search)
        {
            return Contains(instance.ToString(), search);
        }

        public static bool Contains(IPAddress instance, string search)
        {
            return Contains(SafeConvert.ToString(instance), search);
        }

        public static bool Contains(CultureInfo instance, string search)
        {
            return Contains(SafeConvert.ToString(instance), search);
        }

        public static bool Contains(int instance, string search)
        {
            return Contains(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool Contains(short instance, string search)
        {
            return Contains(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool Contains(short? instance, string search)
        {
            if (instance == null)
            {
                return Contains(string.Empty, search);
            }
            return Contains(instance.ToString(), search);
        }

        #endregion Contains

        #region DoesNotContain

        public static bool DoesNotContain(string instance, string search)
        {
            return !Contains(instance, search);
        }

        public static bool DoesNotContain(DateTime instance, string search)
        {
            return DoesNotContain(instance.ToString(), search);
        }

        public static bool DoesNotContain(DateTime? instance, string search)
        {
            return DoesNotContain(instance.ToString(), search);
        }

        public static bool DoesNotContain(IPAddress instance, string search)
        {
            return DoesNotContain(SafeConvert.ToString(instance), search);
        }

        public static bool DoesNotContain(CultureInfo instance, string search)
        {
            return DoesNotContain(SafeConvert.ToString(instance), search);
        }

        public static bool DoesNotContain(int instance, string search)
        {
            return DoesNotContain(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool DoesNotContain(short instance, string search)
        {
            return DoesNotContain(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool DoesNotContain(short? instance, string search)
        {
            return DoesNotContain(instance.ToString(), search);
        }

        #endregion

        #region StartsWith

        public static bool StartsWith(string instance, string search)
        {
            return instance.StartsWith(search, StringComparison.OrdinalIgnoreCase);
        }

        public static bool StartsWith(DateTime instance, string search)
        {
            return StartsWith(instance.ToString(), search);
        }

        public static bool StartsWith(DateTime? instance, string search)
        {
            return StartsWith(instance.ToString(), search);
        }

        public static bool StartsWith(IPAddress instance, string search)
        {
            return StartsWith(SafeConvert.ToString(instance), search);
        }

        public static bool StartsWith(CultureInfo instance, string search)
        {
            return StartsWith(SafeConvert.ToString(instance), search);
        }

        public static bool StartsWith(int instance, string search)
        {
            return StartsWith(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool StartsWith(short instance, string search)
        {
            return StartsWith(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool StartsWith(short? instance, string search)
        {
            return StartsWith(instance.ToString(), search);
        }

        #endregion StartsWith

        #region EndsWith

        public static bool EndsWith(string instance, string search)
        {
            return instance.EndsWith(search, StringComparison.OrdinalIgnoreCase);
        }

        public static bool EndsWith(DateTime instance, string search)
        {
            return EndsWith(instance.ToString(), search);
        }

        public static bool EndsWith(DateTime? instance, string search)
        {
            return EndsWith(instance.ToString(), search);
        }

        public static bool EndsWith(IPAddress instance, string search)
        {
            return EndsWith(SafeConvert.ToString(instance), search);
        }

        public static bool EndsWith(CultureInfo instance, string search)
        {
            return EndsWith(SafeConvert.ToString(instance), search);
        }

        public static bool EndsWith(int instance, string search)
        {
            return EndsWith(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool EndsWith(short instance, string search)
        {
            return EndsWith(instance.ToString(CultureInfo.CurrentCulture), search);
        }

        public static bool EndsWith(short? instance, string search)
        {
            return EndsWith(instance.ToString(), search);
        }

        #endregion EndsWith

        #region WithinThePastDays

        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
        public static bool WithinThePastDays(string instance, string search)
        {
            return false;
        }

        public static bool WithinThePastDays(DateTime instance, string search)
        {
            DateTime daysAgo = DateTime.UtcNow.AddDays(-1 * SafeConvert.ToInt32(search));
            return daysAgo < instance;
        }

        public static bool WithinThePastDays(DateTime? instance, string search)
        {
            if (instance.HasValue)
            {
                return WithinThePastDays((DateTime)instance, search);
            }
            return true;
        }

        #endregion
    }
}